package cn.com.myspring.demo.aop;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;

import cn.com.myspring.framework.aop.aspect.MYJoinPoint;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LogAspect {

    // 在调用一个方法之前，执行before方法
    public void before(MYJoinPoint joinPoint) {
        String name = joinPoint.getThis().getClass().getSimpleName();
        String methodName = joinPoint.getMethod().getName();
        String[] parameterTypesNames = getParameterTypesNames(joinPoint);
        Object[] args = joinPoint.getArguments();
        String paramJson = Arrays.toString(args);
        String parameterTypeName = Arrays.toString(parameterTypesNames).replaceAll("\\[|\\]", "");
        joinPoint.setUserAttribute("startTime_" + joinPoint.getMethod().getName(), System.currentTimeMillis());
        // 前置通知
        log.info("调用{}.{}({})-入参:{}", name, methodName, parameterTypeName, paramJson);
    }

    // 在调用一个方法之后，执行after方法
    public void after(MYJoinPoint joinPoint, Object object) {
        String name = joinPoint.getThis().getClass().getSimpleName();
        String methodName = joinPoint.getMethod().getName();
        String[] parameterTypesNames = getParameterTypesNames(joinPoint);
        String parameterTypeName = Arrays.toString(parameterTypesNames).replaceAll("\\[|\\]", "");
        String resultJson = null;
        if (object != null) {
            resultJson = object.toString();
        }
        log.info("调用{}.{}({})-出参:{}", name, methodName, parameterTypeName, resultJson);
        long startTime = (Long) joinPoint.getUserAttribute("startTime_" + joinPoint.getMethod().getName());
        long endTime = System.currentTimeMillis();
        log.info("运行时间:{}ms", (endTime - startTime));
    }

    public void afterThrowing(MYJoinPoint joinPoint, Throwable ex) {
        log.info("出现异常" + "\nTargetObject:" + joinPoint.getThis() + "\nArgs:"
                + Arrays.toString(joinPoint.getArguments()) + "\nThrows:" + ex.getMessage());
    }

    private String[] getParameterTypesNames(MYJoinPoint joinPoint) {
        Method[] methods = joinPoint.getThis().getClass().getMethods();
        Method currMethod = null;
        for (Method method : methods) {
            if (joinPoint.getMethod().getName().equals(method.getName())) {
                currMethod = method;
            }
        }
        Parameter[] parameters = currMethod.getParameters();
        String[] parameterTypesNames = new String[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            parameterTypesNames[i] = parameters[i].getType().getSimpleName() + " " + parameters[i].getName();
        }
        return parameterTypesNames;
    }

}
